/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Node, Parser, HtmlRenderer, XmlRenderer } from './commonmark.js';


// 将节点添加到另一个节点的子节点列表的末尾
function appendChild_TEST() {
    let linkNode = new Node('link');
    linkNode.destination = 'https://www.example.com';
    linkNode.title = 'Example Link Title';

    let insertNode = new Node('list');

    let paragraphNode = new Node('paragraph');
    paragraphNode.literal='This is a paragraph'
    paragraphNode.prependChild(insertNode);

    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        paragraphNode.appendChild(linkNode);
    }
    let endTime = Date.now()

    if(linkNode !== paragraphNode._lastChild){
        throw new Error('commonmark-js_appendChild Error')
    }
    print(`commonmark-js_appendChild: ${endTime - startTime} ms`)
}

// 将节点添加到另一个节点的子节点列表的开头
function prependChild_TEST() {
    let node = new Node('link');
    node.literal = 'This is a link';

    let insertNode = new Node('list');

    let linkNode = new Node('link');
    linkNode.destination = 'https://www.example.com';
    node.appendChild(insertNode);

    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        node.prependChild(linkNode);
    }
    let endTime = Date.now()

    if(linkNode !== node._firstChild ){
        throw new Error('commonmark-js_prependChild Error')
    }
    print(`commonmark-js_prependChild: ${endTime - startTime} ms`)
}

// 将一个节点从其父节点的子节点列表中移除
function unlink_TEST() {
    let linkNode = new Node('link');
    linkNode.destination = 'https://www.example.com';
    let paragraphNode = new Node('paragraph');
    paragraphNode.literal='This is a paragraph'
    paragraphNode.appendChild(linkNode);

    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        linkNode.unlink();
    }
    let endTime = Date.now()

    if(linkNode == paragraphNode._lastChild ){
        throw new Error('commonmark-js_unlink Error')
    }
    print(`commonmark-js_unlink: ${endTime - startTime} ms`)
}

// 在指定的参考节点之后插入一个新的兄弟节点
function insertAfter_TEST() {
    let insertNode = new Node('list');
    let item = new Node('item')
    let documentNode = new Node('document')
    
    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        insertNode.appendChild(item)
        insertNode._lastChild.insertAfter(documentNode)
    }
    let endTime = Date.now()
    
    if(insertNode._lastChild !== documentNode){
        throw new Error('commonmark-js_insertAfter Error')
    }
    print(`commonmark-js_insertAfter: ${endTime - startTime} ms`)
}

// 在指定的参考节点之前插入一个新的兄弟节点
function insertBefore_TEST() {
    let insertNode = new Node('list');
    let item = new Node('item')
    let documentNode = new Node('document')

    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        insertNode.prependChild(item)
        insertNode._firstChild.insertBefore(documentNode)
    }
    let endTime = Date.now()

    if(insertNode._firstChild !== documentNode){
        throw new Error('commonmark-js_insertBefore Error')
    }
    print(`commonmark-js_insertBefore: ${endTime - startTime} ms`)
}

// 遍历和处理节点树
function walker_TEST() {
    let paragraphNode = new Node('paragraph');
    let rootNode = new Node('document');
    rootNode.appendChild(paragraphNode);
    let walker;
    
    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        walker = rootNode.walker()
    }
    let endTime = Date.now()
    
    if(walker.current.type !== rootNode.type){
        throw new Error('commonmark-js_walker Error')
    }
    print(`commonmark-js_walker: ${endTime - startTime} ms`)
}

// 解析输入字符串，将其转换为抽象语法树/文档对象
function Parser_TEST() {
    let parser = new Parser();
    const input = '# Heading 1\n## Heading 2\n### Heading 3';
    let ast;

    let startTime = Date.now()
    for (let i = 0; i < 10000; i++) {
        ast = parser.parse(input);
    }
    let endTime = Date.now()
    
    if(ast._firstChild.type !== 'heading'){
        throw new Error('commonmark-js_Parser Error')
    }
    print(`commonmark-js_Parser: ${endTime - startTime} ms`)
}

// 将抽象语法树转换为HTML字符串
function render_TEST_01() {
    let parser = new Parser();
    const input = 
        "*斜体文本*\n" +
        "**粗体文本**\n" +
        "***粗斜体文本***\n" +
        "<u>带下划线的文本</u>\n" +
        "- 第一项\n" +
        "- 第二项\n" +
        "- 第三项\n" +
        "- 第2篇\n" +
        "	* 第2.1章\n" +
        "		+ 第2.1.1节\n" +
        "1. 第一项\n" +
        "2. 第二项\n" +
        "3. 第三项\n" +
        "1. 第一项：\n" +
        "    - 第一项嵌套的第一个元素\n" +
        "    - 第一项嵌套的第二个元素\n" +
        "2. 第二项：\n" +
        "    - 第二项嵌套的第一个元素\n" +
        "    - 第二项嵌套的第二个元素\n" +
        "> 区块引用\n" +
        "> 菜鸟教程\n" +
        "> 学的不仅是技术更是梦想\n" +
        "`console.logf()` 函数\n" +
        "```javascript\n" +
        "$(document).ready(function () {\n" +
        "    alert('runoob');\n" +
        "});\n" +
        "```\n" +
        "这是一个链接 [菜鸟教程](https://www.runoob.com)  \n" +
        "![runoob 图标](http://static.runoob.com/images/runoob-logo.png)  \n" +
        "使用 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> 重启电脑 \n ";
    const ast = parser.parse(input);
    let renderer= new HtmlRenderer();

    let html;
    let startTime = Date.now()
    for (let i = 0; i < 10000; i++) {
        html = renderer.render(ast);
    }
    let endTime = Date.now()
    
    if(!/<li>.*<\/li>/.test(html)){
        throw new Error('commonmark-js_render Error: HTML does not contain <li> element')
    }
    print(`commonmark-js_render(HTML): ${endTime - startTime} ms`)
}

// 将抽象语法树转换为XML字符串
function render_TEST_02() {
    let parser = new Parser();
    const input =      
        "*斜体文本*\n" +
        "**粗体文本**\n" +
        "***粗斜体文本***\n" +
        "<u>带下划线的文本</u>\n" +
        "- 第一项\n" +
        "- 第二项\n" +
        "- 第三项\n" +
        "- 第2篇\n" +
        "	* 第2.1章\n" +
        "		+ 第2.1.1节\n" +
        "1. 第一项\n" +
        "2. 第二项\n" +
        "3. 第三项\n" +
        "1. 第一项：\n" +
        "    - 第一项嵌套的第一个元素\n" +
        "    - 第一项嵌套的第二个元素\n" +
        "2. 第二项：\n" +
        "    - 第二项嵌套的第一个元素\n" +
        "    - 第二项嵌套的第二个元素\n" +
        "> 区块引用\n" +
        "> 菜鸟教程\n" +
        "> 学的不仅是技术更是梦想\n" +
        "`console.logf()` 函数\n" +
        "```javascript\n" +
        "$(document).ready(function () {\n" +
        "    alert('runoob');\n" +
        "});\n" +
        "```\n" +
        "这是一个链接 [菜鸟教程](https://www.runoob.com)  \n" +
        "![runoob 图标](http://static.runoob.com/images/runoob-logo.png)  \n" +
        "使用 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> 重启电脑 \n ";
    const ast = parser.parse(input);
    let renderers = new XmlRenderer();

    let xml;
    let startTime = Date.now()
    for (let i = 0; i < 10000; i++) {
        xml = renderers.render(ast);
    }
    let endTime = Date.now()

    const regex = /<(\w+)([^>]*)>(.*?)<\/\1>/g;
    if(!regex.test(xml)){
        throw new Error('commonmark-js_render Error: XML does not regex')
    }
    print(`commonmark-js_render(XML): ${endTime - startTime} ms`)
}

// 返回当前节点的下一个兄弟节点
function next_TEST() {
    const rootNode = new Node('document');
    const paragraphNode = new Node('paragraph');
    const textNode = new Node('text');

    paragraphNode.appendChild(textNode);
    rootNode.appendChild(paragraphNode);
    let walkerNext;

    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        let walker = rootNode.walker();
        walkerNext = walker.next()
    }
    let endTime = Date.now()
    
    if(Object.keys(walkerNext)[0] !== 'entering'){
        throw new Error('commonmark-js_next Error')
    }
    print(`commonmark-js_next: ${endTime - startTime} ms`)
}

// 将遍历器重置为从指定的节点开始遍历
function resumeAt_TEST() {
    const rootNode = new Node('document');
    const listNode = new Node('list');
    const listItemNode1 = new Node('item');

    listNode.appendChild(listItemNode1);
    rootNode.appendChild(listNode);
    
    let walker= rootNode.walker()
    let startTime = Date.now()
    for (let i = 0; i < 2000000; i++) {
        walker.resumeAt(listNode, true)
    }
    let endTime = Date.now()
    
    if(walker.current.type !== 'list'){
        throw new Error('commonmark-js_resumeAt Error')
    }
    print(`commonmark-js_resumeAt: ${endTime - startTime} ms`) 
}

function HtmlRenderer_TEST() {
    const input = 
        "*斜体文本*\n" +
        "**粗体文本**\n" +
        "***粗斜体文本***\n" +
        "<u>带下划线的文本</u>\n" +
        "- 第一项\n" +
        "- 第二项\n" +
        "- 第三项\n" +
        "- 第四项\n" +
        "- 第2篇\n" +
        "	* 第2.1章\n" +
        "		+ 第2.1.1节\n" +
        "1. 第一项\n" +
        "2. 第二项\n" +
        "3. 第三项\n" +
        "1. 第一项：\n" +
        "    - 第一项嵌套的第一个元素\n" +
        "    - 第一项嵌套的第二个元素\n" +
        "    - 第一项嵌套的第三个元素\n" +
        "    - 第一项嵌套的第四个元素\n" +
        "2. 第二项：\n" +
        "    - 第二项嵌套的第一个元素\n" +
        "    - 第二项嵌套的第二个元素\n" +
        "    - 第二项嵌套的第三个元素\n" +
        "    - 第二项嵌套的第四个元素\n" +
        "> 区块引用\n" +
        "> 学的不仅是技术更是梦想\n" +
        "`console.logf()` 函数\n" +
        "```javascript\n" +
        "$(document).ready(function () {\n" +
        "    alert('runoob');\n" +
        "});\n" +
        "```\n" +
        "![runoob 图标](http://static.runoob.com/images/runoob-logo.png)  \n" +
        "使用 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> 重启电脑 \n ";
    
    let renderer;
    let startTime = Date.now()
    for (let i = 0; i < 300000; i++) {
        renderer = new HtmlRenderer();
    }
    let endTime = Date.now()

    let parser = new Parser();
    const ast = parser.parse(input);
    let html = renderer.render(ast);
    
    if(!/<li>.*<\/li>/.test(html)){
        throw new Error('commonmark-js_HtmlRenderer Error: HTML does not contain <li> element')
    }
    print(`commonmark-js_HtmlRenderer: ${endTime - startTime} ms`)
}

function XmlRenderer_TEST() {
    const input =  
        "*斜体文本*\n" +
        "**粗体文本**\n" +
        "***粗斜体文本***\n" +
        "<u>带下划线的文本</u>\n" +
        "- 第一项\n" +
        "- 第二项\n" +
        "- 第三项\n" +
        "- 第四项\n" +
        "- 第2篇\n" +
        "	* 第2.1章\n" +
        "		+ 第2.1.1节\n" +
        "1. 第一项\n" +
        "2. 第二项\n" +
        "3. 第三项\n" +
        "1. 第一项：\n" +
        "    - 第一项嵌套的第一个元素\n" +
        "    - 第一项嵌套的第二个元素\n" +
        "    - 第一项嵌套的第三个元素\n" +
        "    - 第一项嵌套的第四个元素\n" +
        "2. 第二项：\n" +
        "    - 第二项嵌套的第一个元素\n" +
        "    - 第二项嵌套的第二个元素\n" +
        "    - 第二项嵌套的第三个元素\n" +
        "    - 第二项嵌套的第四个元素\n" +
        "> 区块引用\n" +
        "> 学的不仅是技术更是梦想\n" +
        "`console.logf()` 函数\n" +
        "```javascript\n" +
        "$(document).ready(function () {\n" +
        "    alert('runoob');\n" +
        "});\n" +
        "```\n" +
        "![runoob 图标](http://static.runoob.com/images/runoob-logo.png)  \n" +
        "使用 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> 重启电脑 \n ";

    let renderers;
    let startTime = Date.now();
    for (let i = 0; i < 300000; i++) {
        renderers = new XmlRenderer();
    }
    let endTime = Date.now();

    let parser = new Parser();
    const ast = parser.parse(input);
    let xml = renderers.render(ast);

    const regex = /<(\w+)([^>]*)>(.*?)<\/\1>/g;
    if(!regex.test(xml)){
        throw new Error('commonmark-js_XmlRenderer Error: XML does not regex')
    }
    print(`commonmark-js_XmlRenderer: ${endTime - startTime} ms`)
}

function Switch() {
    appendChild_TEST()
    prependChild_TEST()
    unlink_TEST()
    insertAfter_TEST()
    insertBefore_TEST()
    walker_TEST()
    Parser_TEST()
    render_TEST_01() 
    render_TEST_02()
    next_TEST()
    resumeAt_TEST()
    HtmlRenderer_TEST()
    XmlRenderer_TEST()
}
Switch()


